#![no_std]
#![no_main]
#![feature(naked_functions)]

use core::{
    arch::{asm, global_asm, naked_asm},
    panic::PanicInfo,
};

use riscv64::register::{self, mstatus::MPP};

global_asm!(include_str!("sbi_boot.s"));

#[unsafe(no_mangle)]
#[unsafe(link_section = ".benos")]
#[naked]
#[allow(undefined_naked_function_abi)]
unsafe fn benos_bin() {
    cfg_if::cfg_if! {
        if #[cfg(feature = "with_benos")] {
            unsafe {naked_asm!(".incbin \"sbi/benos.bin\"");}
        } else {
            unsafe {naked_asm!("");}
        }
    }
}

#[panic_handler]
fn panic_handler(_info: &PanicInfo) -> ! {
    loop {}
}

const FW_JUMP_ADDR: usize = 0x80200000;
#[unsafe(no_mangle)]
fn sbi_main() {
    // 设置M模式之前的CPU处理模式为S
    let mut status = register::mstatus::read();
    status.set_mpp(MPP::Supervisor);
    status.set_mpie(false);
    register::mstatus::write(status);

    // 设置M模式的Exception Program Counter，用于mret跳转
    register::mpec::write(FW_JUMP_ADDR);
    // 设置S模式异常向量表入口
    register::stvec::write(register::stvec::Stvec::from_bits(FW_JUMP_ADDR));
    // 关闭S模式的中断
    register::sie::write(register::sie::Sie::from_bits(0));
    // 关闭S模式的页表转换
    register::satp::write(register::satp::Satp::from_bits(0));

    // 切换到S模式
    unsafe {
        asm!("mret");
    }
}
